package com.t2two.example.common.utils;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;

import java.math.BigDecimal;
import java.sql.Time;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @version 1.0
 * @description: 日期工具类
 * @author: lifei
 * @date: 2023/6/26 16:35
 */
@Slf4j
public class DateTimeUtil {

    /**
     * 时间格式常量
     */
    public static final String default_format = "yyyy-MM-dd HH:mm:ss";
    public static final String default_format_BiasLine = "yyyy/MM/dd HH:mm:ss";
    public static final String yearMonthDayLine = "yyyy-MM-dd";
    public static final String yearMonthDayBiasLine = "yyyy/MM/dd";
    public static final String DateTime_Millisecond = "yyyy-MM-dd HH:mm:ss.SSS";
    public static final String yyyyMMdd = "yyyyMMdd";
    public static final String yyyyMMddHHmmss = "yyyyMMddHHmmss";
    public static final String YEAR_MONTH = "yyyyMM";
    public static final String CN_yearMonthDay = "yyyy年MM月dd日";
    public static final String DDMM_PATTERN = "ddMM";
    public static final String CN_yearMonth = "yyyy年MM月";

    public static final String yearMonth = "yyyy-MM";

    private static final Long DEFAULT_MAX_TIME_STAMP = 1696175999000L;
    public static TimeZone timeZone = TimeZone.getTimeZone("GMT+8");

    public static final String ZoneIdString = "Asia/Shanghai";

    private static  final DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;

    public enum DateTimeEnum{
        Year("Year","年"),
        Month("Month","月"),
        Day("Day","日"),
        Hour("Hour","时"),
        Minute("Minute","分钟"),
        Second("Second","秒"),
        Millisecond("Millisecond","毫秒"),
        ;
        private String key;
        private String value;

        public String getKey() {
            return key;
        }
        public void setKey(String key) {
            this.key = key;
        }
        public String getValue() {
            return value;
        }
        public void setValue(String value) {
            this.value = value;
        }
        DateTimeEnum(String key,String value){
            this.key = key;
            this.value = value;
        }
    }

    public static void main(String[] args) {
        List<Date> dateBetween = getDateBetween(new Date(1706118641000L), new Date(1706284241000L), true, true);
        System.out.println(JSONObject.toJSONString(dateBetween));

//        Date dateHaveZoneReduceByDateTime = getDateHaveZoneReduceByDateTime(1704691800000L);
//        System.out.println(JSONObject.toJSONString(dateHaveZoneReduceByDateTime));
    }

    /**
     * 获取标准时间【返回毫秒】
     * @return
     */
    public static int getRawOffset(){
        return timeZone.getRawOffset();
    }

    /**
     * 日期转Time，时间转化为东八区【北京时间】
     * @param time
     * @return
     */
    public static Time getTimeHaveZoneByDateTime(Long time){
        if(time==null){
            return null;
        }
        Instant instant = Instant.ofEpochMilli(time);
        ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of(ZoneIdString));
//        LocalDateTime utcTime = LocalDateTime.parse(time.toString(), formatter);
//        ZonedDateTime zonedDateTime = utcTime.atZone(ZoneId.of(ZoneIdString));
        return new Time(zonedDateTime.toInstant().toEpochMilli());
//        return new Time(time+timeZone.getRawOffset());
    }

    public static Date getDateHaveZoneByDateTime(Long time){
        if(time==null){
            return null;
        }
        Instant instant = Instant.ofEpochMilli(time);
        ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of(ZoneIdString));
//        LocalDateTime utcTime = LocalDateTime.parse(time.toString(), formatter);
//        ZonedDateTime zonedDateTime = utcTime.atZone(ZoneId.of(ZoneIdString));
        return new Time(zonedDateTime.toInstant().toEpochMilli());
//        return new Date(time+timeZone.getRawOffset());
    }

    /**
     * 日期转Time，时间转化为东八区【北京时间】，前端传正常数据，先减8小时再保存
     * @param time
     * @return
     */
    public static Time getTimeHaveZoneReduceByDateTime(Long time){
        if(time==null){
            return null;
        }
        Instant instant = Instant.ofEpochMilli(time);
        ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of(ZoneIdString));
//        LocalDateTime utcTime = LocalDateTime.parse(time.toString(), formatter);
//        ZonedDateTime zonedDateTime = utcTime.atZone(ZoneId.of(ZoneIdString));
        return new Time(zonedDateTime.toInstant().toEpochMilli());
//        return new Time(time-timeZone.getRawOffset());
    }

    public static Date getDateHaveZoneReduceByDateTime(Long time){
        if(time==null){
            return null;
        }
        Instant instant = Instant.ofEpochMilli(time);
        ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of(ZoneIdString));
//        LocalDateTime utcTime = LocalDateTime.parse(time.toString(), formatter);
//        ZonedDateTime zonedDateTime = utcTime.atZone(ZoneId.of(ZoneIdString));
        return new Time(zonedDateTime.toInstant().toEpochMilli());
//        return new Date(time-timeZone.getRawOffset());
    }

    /**
     * 字符串转日期
     * @param dateString
     * @param pattern
     * @return
     * @throws ParseException
     */
    public static Date string2Date(String dateString, String pattern) throws ParseException {
        String fRTN = StringUtils.isNotBlank(pattern) ? pattern : default_format;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(fRTN);
        return simpleDateFormat.parse(dateString);
    }

    /**
     * 日期转字符串格式
     * @param date
     * @param pattern
     * @return
     */
    public static String date2String(Date date,String pattern) {
        String tRTN = StringUtils.isNotBlank(pattern) ? pattern : default_format;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(tRTN);
        return simpleDateFormat.format(date);
    }


    /**
     * 获取指定月的第一天【参数为空时默认当前月】
     * @param month
     * @return
     */
    public static String firstMonthDay(Date month){
        Calendar calendar = Calendar.getInstance();
        if(Objects.nonNull(month)){
            calendar.setTime(month);
        }
        calendar.add(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat(yearMonthDayLine);
        String firstDay = yyyyMMdd.format(calendar.getTime());
        firstDay = firstDay + " 00:00:00";
        return firstDay;
    }

    /**
     * 获取指定月的第一天，Date类型的格式返回【参数为空时默认当前月】
     * @param month
     * @return
     */
    public static Date firstMonthDayReturnDate(Date month){
        Calendar calendar = Calendar.getInstance();
        if(Objects.nonNull(month)){
            calendar.setTime(month);
        }
        calendar.add(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY,0);
        calendar.set(Calendar.MINUTE,0);
        calendar.set(Calendar.SECOND,0);
        calendar.set(Calendar.MILLISECOND,0);
        return calendar.getTime();
    }

    /**
     * 获取指定月的最后一天【参数为空时默认当前月】
     * @param month
     * @return
     */
    public static String lastMonthDay(Date month){
        Calendar calendar = Calendar.getInstance();
        if(Objects.nonNull(month)){
            calendar.setTime(month);
        }
        calendar.add(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat(yearMonthDayLine);
        String lastDay = yyyyMMdd.format(calendar.getTime());
        lastDay = lastDay + " 23:59:59";
        return lastDay;
    }

    /**
     * 获取指定月的最后一天，Date类型的格式返回【参数为空时默认当前月】
     * @param month
     * @return
     */
    public static Date lastMonthDayReturnDate(Date month){
        Calendar calendar = Calendar.getInstance();
        if(Objects.nonNull(month)){
            calendar.setTime(month);
        }
        calendar.add(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        return joinDateAndTime(calendar.getTime(),new Date(DEFAULT_MAX_TIME_STAMP));
    }

    /**
     * 根据指定日期获取之前num天的数据
     * num>0，获取之后的数据，num<0，获取之前的数据
     * num需要传
     * @param date
     * @param num
     * @param flag true:指定日期之前或之后的 00:00:00，false:指定日期之前或之后的 23:59:59。null:当前时间
     * @return
     */
    public static String getBeforeLastStringByDateNum(Date date,Integer num,Boolean flag){
        if(Objects.isNull(date) || num==null){
            return null;
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(default_format);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE,num);
        if(flag!=null){
            SimpleDateFormat yyyyMMdd = new SimpleDateFormat(yearMonthDayLine);
            if(flag){
                String firstDay = yyyyMMdd.format(calendar.getTime());
                firstDay = firstDay + " 00:00:00";
                return firstDay;
            }else {
                String lastDay = yyyyMMdd.format(calendar.getTime());
                lastDay = lastDay + " 23:59:59";
                return lastDay;
            }
        }
        return simpleDateFormat.format(calendar.getTime());
    }

    /**
     * 根据传入时间比较时间是否相等
     * @param time
     * @param time1
     * @return
     */
    public static Boolean sqlTimeEquals(Time time,Time time1){
        if(time==null && time1==null){
            return true;
        }
        if((time!=null && time1==null) || (time==null && time1!=null)){
            return false;
        }
        Time time2 = new Time(time.getTime());
        Time time3 = new Time(time1.getTime());
        String str = String.valueOf(time2);
        String str1 = String.valueOf(time3);
        return str.equals(str1);
    }

    /**
     * 根据日期比较时间是否相等
     * @param date
     * @param date1
     * @return
     */
    public static Boolean sqlTimeEquals(Date date,Date date1){
        if(date==null && date1==null){
            return true;
        }
        if((date!=null && date1==null) || (date==null && date1!=null)){
            return false;
        }
        Time time2 = new Time(date.getTime());
        Time time3 = new Time(date1.getTime());
        String str = String.valueOf(time2);
        String str1 = String.valueOf(time3);
        return str.equals(str1);
    }
    /**
     * 比较两个日期是否相等
     * @param date
     * @param date1
     * @return
     */
    public static Boolean sqlDateTimeEquals(Date date, Date date1,String pattern){
        if(date==null && date1==null){
            return true;
        }
        if((date!=null && date1==null) || (date==null && date1!=null)){
            return false;
        }
        String tRTN = StringUtils.isNotBlank(pattern) ? pattern : default_format;
        String str = date2String(date, tRTN);
        String str1 = date2String(date1, tRTN);
        return str.equals(str1);
    }

    /**
     * 比较传的日期的年月日是否相等
     * @param date
     * @param date1
     * @return
     */
    public static Boolean yearMonthDayEquals(Date date,Date date1){
        if(date==null && date1==null){
            return true;
        }
        if((date!=null && date1==null) || (date==null && date1!=null)){
            return false;
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(yearMonthDayLine);
        String format = simpleDateFormat.format(date);
        String format1 = simpleDateFormat.format(date1);
        return format.equals(format1);
    }

    /**
     * 第一个时间小于第二个时间返回true
     * @param beforeDate
     * @param afterDate
     * @return
     */
    public static Boolean dateBeforeLessThan(Date beforeDate, Date afterDate){
        if(Objects.isNull(beforeDate) || Objects.isNull(afterDate)){
            return false;
        }
        if(beforeDate.getTime()<0){
            beforeDate = getDateHaveZoneByDateTime(beforeDate.getTime());
        }
        if(afterDate.getTime()<0){
            afterDate = getDateHaveZoneByDateTime(afterDate.getTime());
        }
        Calendar beforeCalendar = Calendar.getInstance();
        beforeCalendar.setTime(beforeDate);
        Calendar afterCalendar = Calendar.getInstance();
        afterCalendar.setTime(afterDate);
        afterCalendar.set(Calendar.DAY_OF_MONTH, beforeCalendar.get(Calendar.DAY_OF_MONTH));
        afterCalendar.set(Calendar.MONTH, beforeCalendar.get(Calendar.MONTH));
        afterCalendar.set(Calendar.YEAR, beforeCalendar.get(Calendar.YEAR));
        long l = beforeCalendar.getTimeInMillis() - afterCalendar.getTimeInMillis();
        if(l<=0){
            return true;
        }
        return false;
    }

    /**
     * 第一个时间在第二个时间之后返回 true
     * @param firstDate
     * @param lastDate
     * @return
     */
    public static Boolean dateAfterLessThan(Date firstDate, Date lastDate){
        if(Objects.isNull(firstDate) || Objects.isNull(lastDate)){
            return false;
        }
        if(firstDate.getTime()<0){
            firstDate = getDateHaveZoneByDateTime(firstDate.getTime());
        }
        if(lastDate.getTime()<0){
            lastDate = getDateHaveZoneByDateTime(lastDate.getTime());
        }
        Calendar firstCalendar = Calendar.getInstance();
        firstCalendar.setTime(firstDate);

        Calendar lastCalendar = Calendar.getInstance();
        lastCalendar.setTime(lastDate);
        lastCalendar.set(Calendar.DAY_OF_MONTH, firstCalendar.get(Calendar.DAY_OF_MONTH));
        lastCalendar.set(Calendar.MONTH, firstCalendar.get(Calendar.MONTH));
        lastCalendar.set(Calendar.YEAR, firstCalendar.get(Calendar.YEAR));
        long l = firstCalendar.getTimeInMillis() - lastCalendar.getTimeInMillis();
        if(l>0){
            return true;
        }
        return false;
    }

    /**
     * 拼接日期和时间，把第一个参数的年月日和第二个参数的时分秒拼接到一起
     * @param date
     * @param time
     * @return
     */
    public static Date joinDateAndTime(Date date, Time time){
        if(Objects.isNull(date) || Objects.isNull(time)){
            return null;
        }
        if(date.getTime()<0){
            date = getDateHaveZoneByDateTime(date.getTime());
        }
        if(time.getTime()<0){
            time = getTimeHaveZoneByDateTime(time.getTime());
        }
        Calendar firstCalendar = Calendar.getInstance();
        firstCalendar.setTime(date);
        Calendar lastCalendar = Calendar.getInstance();
        lastCalendar.setTime(time);
        lastCalendar.set(Calendar.DAY_OF_MONTH, firstCalendar.get(Calendar.DAY_OF_MONTH));
        lastCalendar.set(Calendar.MONTH, firstCalendar.get(Calendar.MONTH));
        lastCalendar.set(Calendar.YEAR, firstCalendar.get(Calendar.YEAR));
        return lastCalendar.getTime();
    }

    /**
     * 拼接日期和时间，把第一个参数的年月日和第二个参数的时分秒拼接到一起
     * @param firstDate
     * @param lastDate
     * @return
     */
    public static Date joinDateAndTime(Date firstDate, Date lastDate){
        if(Objects.isNull(firstDate) || Objects.isNull(lastDate)){
            return null;
        }
        if(firstDate.getTime()<0){
            firstDate = getDateHaveZoneByDateTime(firstDate.getTime());
        }
        if(lastDate.getTime()<0){
            lastDate = getDateHaveZoneByDateTime(lastDate.getTime());
        }
        Calendar firstCalendar = Calendar.getInstance();
        firstCalendar.setTime(firstDate);
        Calendar lastCalendar = Calendar.getInstance();
        lastCalendar.setTime(lastDate);
        lastCalendar.set(Calendar.DAY_OF_MONTH, firstCalendar.get(Calendar.DAY_OF_MONTH));
        lastCalendar.set(Calendar.MONTH, firstCalendar.get(Calendar.MONTH));
        lastCalendar.set(Calendar.YEAR, firstCalendar.get(Calendar.YEAR));
        return lastCalendar.getTime();
    }

    /**
     * date 日期在 num天之前或之后的日期，num为正数：num天之后的日期，num为负数：num天之前的日期
     * @param date
     * @param num
     * @return
     */
    public static Date dayBeforeAfter(Date date,Integer num){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE,num);
        return calendar.getTime();
    }

    /**
     * date 日期在 num秒之前或之后的日期，num为正数：num秒之后的日期，num为负数：num秒之前的日期
     * @param date
     * @param num
     * @return
     */
    public static Date secondBeforeAfter(Date date,Integer num){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.SECOND,num);
        return calendar.getTime();
    }

    /**
     * 处理date 日期在 num分钟之前或之后的日期，num为正数：num分钟之后的日期，num为负数：num分钟之前的日期
     * @param date
     * @param num
     * @param minuteFlag 是否初始化分钟为0，true：初始化
     * @param secondFlag 是否初始化秒为0，true：初始化
     * @return
     */
    public static Date minuteBeforeAfter(Date date, Integer num,Boolean minuteFlag,Boolean secondFlag){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        if(secondFlag!=null && secondFlag){
            calendar.set(Calendar.SECOND,0);
        }
        if(minuteFlag!=null && minuteFlag){
            calendar.set(Calendar.MINUTE,0);
        }
        calendar.add(Calendar.MINUTE,num);
        return calendar.getTime();
    }

    /**
     * 查询两个日期之间的所有日期，
     * @param startDate
     * @param endDate
     * @param startFlag 为true，查询时包含开始日期，为false或null时，不包含
     * @param endFlag 为true，查询时包含结束日期，为false或null时，不包含
     * @return
     */
    public static List<Date> getDateBetween(Date startDate, Date endDate, Boolean startFlag, Boolean endFlag){
        if(Objects.isNull(startDate) || Objects.isNull(endDate)){
            return Collections.EMPTY_LIST;
        }
        if(startDate.after(endDate)){
            Date date = new Date();
            date.setTime(endDate.getTime());
            endDate.setTime(startDate.getTime());
            startDate.setTime(date.getTime());
        }
        List<Date> datesInRange = new ArrayList<>();
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(startDate);
        if(startFlag==null || !startFlag){
            calendar.add(Calendar.DATE,1);
        }
        Calendar endCalendar = new GregorianCalendar();
        endCalendar.setTime(endDate);
        if(endFlag==null || !endFlag){
            endCalendar.add(Calendar.DATE,-1);
        }
        while (calendar.before(endCalendar) || date2String(calendar.getTime(),yearMonthDayLine).equals(date2String(endCalendar.getTime(),yearMonthDayLine))){
            Date time = calendar.getTime();
            datesInRange.add(time);
            calendar.add(Calendar.DATE,1);
        }
        return datesInRange;
    }

    /**
     * 获取某个时间最大和秒数
     * @param date
     * @return
     */
    public static Date getMaxSecond(Date date){
        if(date.getTime()<0){
            date = getDateHaveZoneByDateTime(date.getTime());
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.SECOND,59);
        return calendar.getTime();
    }

    /**
     * 获取请假时长
     * @param startDate 请假开始时间
     * @param endDate 请假结束时间
     * @param morningStartDate 上午上班打卡时间
     * @param morningEndDate 上午下班打卡时间
     * @param afternoonStartDate 下午上班打卡时间
     * @param afternoonEndDate 下午下班打卡时间
     * @param dateList 工作日时间
     * @param morningHour 上午假期时长间隔
     * @param afternoonHour 下午请假时长间隔
     * @return
     * @throws ParseException
     */
    public static Double getLeaveHours(Date startDate,Date endDate,Date morningStartDate,Date morningEndDate,Date afternoonStartDate,Date afternoonEndDate,List<Date> dateList,Double morningHour,Double afternoonHour) throws ParseException {
        if(startDate.after(endDate)){
            Date date = new Date();
            date.setTime(endDate.getTime());
            endDate.setTime(startDate.getTime());
            startDate.setTime(date.getTime());
        }
        //排除法定节假日及双休日，添加法定调休日
        //dateList：工作日
        List<Date> dateBetween = getDateBetween(startDate, endDate, true, true);
        List<String> dateBetweenString = null;
        if(CollectionUtils.isNotEmpty(dateBetween)){
            dateBetweenString = dateBetween.stream().map(x->date2String(x,yearMonthDayLine)).collect(Collectors.toList());
        }
        List<String> dateListString = null;
        if(CollectionUtils.isNotEmpty(dateList)){
            dateListString = dateList.stream().map(x -> date2String(x, yearMonthDayLine)).collect(Collectors.toList());
        }
        if(CollectionUtils.isEmpty(dateBetweenString) || CollectionUtils.isEmpty(dateListString)){
            return 0.0;
        }
        //取交集
        List<String> intersection = (List<String>) CollectionUtils.intersection(dateBetweenString, dateListString);
//        List<Date> intersection = (List<Date>) CollectionUtils.intersection(dateBetween, dateList);
        //为空，不存在交集，即非工作日调休，不作数
        if(CollectionUtils.isEmpty(intersection)){
            return 0.0;
        }
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat(yearMonthDayLine);

        List<String> yyyyMMddString = new ArrayList<>();
        for (String d:intersection) {
            yyyyMMddString.add(d);
        }
        String format = yyyyMMdd.format(startDate);
        String format1 = yyyyMMdd.format(endDate);

        //请假是在同一天
        if(format.equals(format1)){
            if(yyyyMMddString.contains(format)){
                Date dateMorningStart = joinDateAndTime(startDate, morningStartDate);
                Date dateMorningEnd = joinDateAndTime(startDate, morningEndDate);
                Date dateAfternoonStart = joinDateAndTime(startDate, afternoonStartDate);
                Date dateAfternoonEnd = joinDateAndTime(startDate, afternoonEndDate);
                //上午请假
                if(sqlTimeEquals(startDate,dateMorningStart) && sqlTimeEquals(endDate,dateMorningEnd)){
                    return morningHour;
                }else if(sqlTimeEquals(startDate,dateMorningStart) && sqlTimeEquals(endDate,dateAfternoonEnd)){
                    //全天请假
                    return morningHour+afternoonHour;
                }else if(sqlTimeEquals(startDate,dateAfternoonStart) && sqlTimeEquals(endDate,dateAfternoonEnd)){
                    //下午请假
                    return afternoonHour;
                }
                return 0.0;
            }
            return 0.0;
        }else {
            Calendar clCalendar=Calendar.getInstance();
            clCalendar.setTime(startDate);
            clCalendar.add(Calendar.DATE, 1);
            String format2 = yyyyMMdd.format(clCalendar.getTime());
            //请假是相邻天
            if (format1.equals(format2)){
                Date morningStart = joinDateAndTime(startDate, morningStartDate);
                Date morningEnd = joinDateAndTime(startDate, morningEndDate);
                Date afternoonStart = joinDateAndTime(startDate, afternoonStartDate);
                Date afternoonEnd = joinDateAndTime(startDate, afternoonEndDate);
                Date morningStart1 = joinDateAndTime(endDate, morningStartDate);
                Date morningEnd1 = joinDateAndTime(endDate, morningEndDate);
                Date afternoonStart1 = joinDateAndTime(endDate, afternoonStartDate);
                Date afternoonEnd1 = joinDateAndTime(endDate, afternoonEndDate);
                //请假的两天都在工作日内
                if(yyyyMMddString.contains(format) && yyyyMMddString.contains(format1)){
                    //请假两天
                    if(sqlTimeEquals(startDate,morningStart) && sqlTimeEquals(endDate,afternoonEnd1)){
                        return (morningHour+afternoonHour)*2;
                    }else if(sqlTimeEquals(startDate,morningStart) && sqlTimeEquals(endDate,morningEnd1)){
                        //第一天请假一天，第二天请假半天
                        return morningHour+morningHour+afternoonHour;
                    }else if(sqlTimeEquals(startDate,afternoonStart) && sqlTimeEquals(endDate,afternoonEnd1)){
                        //第一天请假半天，第二天请假一天
                        return afternoonHour+morningHour+afternoonHour;
                    }else if(sqlTimeEquals(startDate,afternoonStart) && sqlTimeEquals(endDate,morningEnd1)){
                        //第一天请假半天，第二天请假半天
                        return morningHour+afternoonHour;
                    }
                    return 0.0;
                }else if(yyyyMMddString.contains(format) && !yyyyMMddString.contains(format1)){ /// 第一天在工作日内，第二天不在工作日内
                    // 因为第一天在工作日内，如果请假一天，则第一天早上相等
                    if(sqlTimeEquals(startDate,morningStart)){
                        return morningHour+afternoonHour;
                    }else if(sqlTimeEquals(startDate,afternoonStart)){
                        return afternoonHour;
                    }
                }else if(!yyyyMMddString.contains(format) && yyyyMMddString.contains(format1)){ /// 第二天在工作日内，第一天不在工作日内
                    // 因为第二天在工作日内，如果请假一天，则第二天下午相等
                    if(sqlTimeEquals(endDate,afternoonEnd1)){
                        return morningHour+afternoonHour;
                    }else if(sqlTimeEquals(endDate,morningEnd1)){
                        return morningHour;
                    }
                }
                return 0.0;
            }else {
                //存在跨天的情况
                Date morningStart = joinDateAndTime(startDate, morningStartDate);
                Date morningEnd = joinDateAndTime(startDate, morningEndDate);
                Date afternoonStart = joinDateAndTime(startDate, afternoonStartDate);
                Date afternoonEnd = joinDateAndTime(startDate, afternoonEndDate);
                Date morningStart1 = joinDateAndTime(endDate, morningStartDate);
                Date morningEnd1 = joinDateAndTime(endDate, morningEndDate);
                Date afternoonStart1 = joinDateAndTime(endDate, afternoonStartDate);
                Date afternoonEnd1 = joinDateAndTime(endDate, afternoonEndDate);
                int size = yyyyMMddString.size();
                // 例 周六请假 到周一上午，实际请假只有周一上午半天
                if(size==1){
                    if(yyyyMMddString.contains(format) && !yyyyMMddString.contains(format1)){ /// 第一天在工作日内，第二天不在工作日内
                        // 因为第一天在工作日内，如果请假一天，则第一天早上相等
                        if(sqlTimeEquals(startDate,morningStart)){
                            return morningHour+afternoonHour;
                        }else if(sqlTimeEquals(startDate,afternoonStart)){
                            return afternoonHour;
                        }
                    }else if(!yyyyMMddString.contains(format) && yyyyMMddString.contains(format1)){ /// 第二天在工作日内，第一天不在工作日内
                        // 因为第二天在工作日内，如果请假一天，则第二天下午相等
                        if(sqlTimeEquals(endDate,afternoonEnd1)){
                            return morningHour+afternoonHour;
                        }else if(sqlTimeEquals(endDate,morningEnd1)){
                            return morningHour;
                        }
                    }
                    return 0.0;
                }
                //中间存在节假日或双休日
                if(size==2){
                    //请假两天
                    if(sqlTimeEquals(startDate,morningStart) && sqlTimeEquals(endDate,afternoonEnd1)){
                        return (morningHour+afternoonHour)*2;
                    }else if(sqlTimeEquals(startDate,morningStart) && sqlTimeEquals(endDate,morningEnd1)){
                        //第一天请假一天，第二天请假半天
                        return morningHour+morningHour+afternoonHour;
                    }else if(sqlTimeEquals(startDate,afternoonStart) && sqlTimeEquals(endDate,afternoonEnd1)){
                        //第一天请假半天，第二天请假一天
                        return afternoonHour+morningHour+afternoonHour;
                    }else if(sqlTimeEquals(startDate,afternoonStart) && sqlTimeEquals(endDate,morningEnd1)){
                        //第一天请假半天，第二天请假半天
                        return morningHour+afternoonHour;
                    }
                    return 0.0;
                }else {
                    Double hours = (size - 2) * (morningHour+afternoonHour);
                    //请假两天
                    if(sqlTimeEquals(startDate,morningStart) && sqlTimeEquals(endDate,afternoonEnd1)){
                        return (morningHour+afternoonHour)*2+hours;
                    }else if(sqlTimeEquals(startDate,morningStart) && sqlTimeEquals(endDate,morningEnd1)){
                        //第一天请假一天，第二天请假半天
                        return morningHour+afternoonHour+morningHour+hours;
                    }else if(sqlTimeEquals(startDate,afternoonStart) && sqlTimeEquals(endDate,afternoonEnd1)){
                        //第一天请假半天，第二天请假一天
                        return morningHour+afternoonHour+afternoonHour+hours;
                    }else if(sqlTimeEquals(startDate,afternoonStart) && sqlTimeEquals(endDate,morningEnd1)){
                        //第一天请假半天，第二天请假半天
                        return morningHour+afternoonHour+hours;
                    }
                    return 0.0;
                }
            }
        }
    }
    /***
     * 判断两个时间段是否存在交集，true：存在交集，false：不存在交集
     * 开始时间的最大值小于等于结束时间的最小值则说明这两个时间段有交集
     * @param startDateOne 第一个时间段的开始时间
     * @param endDateOne 第一个时间段的结束时间
     * @param startDateTwo 第二个时间段的开始时间
     * @param endDateTwo 第二个时间段的结束时间
     * @param flag  为true，相等时也算有交集
     * @return
     */
    public static Boolean isInterSection(Date startDateOne,Date endDateOne,Date startDateTwo,Date endDateTwo,Boolean flag){
        //为true，相等时也算有交集
        if(Objects.nonNull(flag) && flag){
            //包含 即存在交集
            if((startDateOne.before(startDateTwo)|| startDateOne.getTime()==startDateTwo.getTime())
                    && (endDateOne.after(endDateTwo) || endDateOne.getTime()==endDateTwo.getTime())){
                return true;
            }
            //包含 即存在交集
            if((startDateTwo.before(startDateOne) || startDateTwo.getTime()==startDateOne.getTime())
                    && (endDateTwo.after(endDateOne) || endDateTwo.getTime() == endDateOne.getTime())){
                return true;
            }
            Date maxStartDate = startDateOne;
            if(maxStartDate.before(startDateTwo)){
                maxStartDate = startDateTwo;
            }
            Date minEndDate = endDateOne;
            if(endDateTwo.before(minEndDate)){
                minEndDate = endDateTwo;
            }
            if(maxStartDate.before(minEndDate) || (maxStartDate.getTime() == minEndDate.getTime())){
                return true;
            }
            return  false;
        }else {
            //包含 即存在交集
            if(startDateOne.before(startDateTwo) && endDateOne.after(endDateTwo)){
                return true;
            }
            //包含 即存在交集
            if(startDateTwo.before(startDateOne) && endDateTwo.after(endDateOne)){
                return true;
            }
            Date maxStartDate = startDateOne;
            if(maxStartDate.before(startDateTwo)){
                maxStartDate = startDateTwo;
            }
            Date minEndDate = endDateOne;
            if(endDateTwo.before(minEndDate)){
                minEndDate = endDateTwo;
            }
            if(maxStartDate.before(minEndDate)){
                return true;
            }
            return  false;
        }
    }

    /**
     * 计算两个时间相差多少
     * @param startDate 开始时间
     * @param endDate 结束时间
     * @param timeEnum 返回格式，总共有年，月，日，时，分，秒，毫秒 7种
     * @return
     */
    public static BigDecimal dateSubtractionDate(Date startDate,Date endDate,DateTimeEnum timeEnum){
        if(Objects.isNull(timeEnum) || Objects.isNull(startDate) || Objects.isNull(endDate)){
            return BigDecimal.ZERO;
        }
        if(startDate.after(endDate)){
            Date date = new Date();
            date.setTime(endDate.getTime());
            endDate.setTime(startDate.getTime());
            startDate.setTime(date.getTime());
        }
        Calendar startCalendar = Calendar.getInstance();
        startCalendar.setTime(startDate);
        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(endDate);
        long l = endCalendar.getTimeInMillis() - startCalendar.getTimeInMillis();
        BigDecimal bigDecimal = new BigDecimal(String.valueOf(l));
        switch (timeEnum.getKey()){
            case "Year":
                bigDecimal = new BigDecimal(String.valueOf(l)).divide(new BigDecimal("365"),10,BigDecimal.ROUND_HALF_UP).divide(new BigDecimal("24"),10,BigDecimal.ROUND_HALF_UP).divide(new BigDecimal("60"),10,BigDecimal.ROUND_HALF_UP).divide(new BigDecimal("60"),10,BigDecimal.ROUND_HALF_UP).divide(new BigDecimal("1000"),10,BigDecimal.ROUND_HALF_UP);
                break;
            case "Month":
                bigDecimal = new BigDecimal(String.valueOf(l)).divide(new BigDecimal("12"),10,BigDecimal.ROUND_HALF_UP).divide(new BigDecimal("24"),10,BigDecimal.ROUND_HALF_UP).divide(new BigDecimal("60"),10,BigDecimal.ROUND_HALF_UP).divide(new BigDecimal("60"),10,BigDecimal.ROUND_HALF_UP).divide(new BigDecimal("1000"),10,BigDecimal.ROUND_HALF_UP);
                break;
            case "Day":
                bigDecimal = new BigDecimal(String.valueOf(l)).divide(new BigDecimal("24"),10,BigDecimal.ROUND_HALF_UP).divide(new BigDecimal("60"),10,BigDecimal.ROUND_HALF_UP).divide(new BigDecimal("60"),10,BigDecimal.ROUND_HALF_UP).divide(new BigDecimal("1000"),10,BigDecimal.ROUND_HALF_UP);
                break;
            case "Hour":
                bigDecimal = new BigDecimal(String.valueOf(l)).divide(new BigDecimal("60"),10,BigDecimal.ROUND_HALF_UP).divide(new BigDecimal("60"),10,BigDecimal.ROUND_HALF_UP).divide(new BigDecimal("1000"),10,BigDecimal.ROUND_HALF_UP);
                break;
            case "Minute":
                bigDecimal = new BigDecimal(String.valueOf(l)).divide(new BigDecimal("60"),10,BigDecimal.ROUND_HALF_UP).divide(new BigDecimal("1000"),10,BigDecimal.ROUND_HALF_UP);
                break;
            case "Second":
                bigDecimal = new BigDecimal(String.valueOf(l)).divide(new BigDecimal("1000"),10,BigDecimal.ROUND_HALF_UP);
                break;
            default:
                bigDecimal = new BigDecimal(String.valueOf(l));
                break;
        }
        return bigDecimal;
    }

    /**
     * 判断某个时间是否在另外两个时间之间
     * @param startDate 开始时间
     * @param endDate 结束时间
     * @param middleDate 中间时间
     * @param flag 是否把结束时间换算成秒数为59，true：换算成59，false或null：不处理
     * @return
     */
    public static Boolean dateMiddleDate(Date startDate,Date endDate,Date middleDate,Boolean flag){
        if(Objects.isNull(middleDate) || Objects.isNull(startDate) || Objects.isNull(endDate)){
            return false;
        }
        if(Objects.nonNull(flag) && flag){
            endDate = getMaxSecond(endDate);
        }
        String startDateString = date2String(startDate, null);
        String endDateString = date2String(endDate, null);
        String middleDateString = date2String(middleDate, null);
        //相等也算在之间
        if((middleDate.after(startDate)||middleDateString.equals(startDateString)) && (middleDate.before(endDate)||middleDateString.equals(endDateString))){
            return true;
        }
        return false;
    }

    /**
     * 判断list中是否存在 某两个时间之间的值
     * @param startDate
     * @param endDate
     * @param middleDates
     * @param flag
     * @return
     */
    public static Boolean listDateInDates(Date startDate,Date endDate,List<Date> middleDates,Boolean flag){
        if(CollectionUtils.isEmpty(middleDates) || Objects.isNull(startDate) || Objects.isNull(endDate)){
            return false;
        }
        if(Objects.nonNull(flag) && flag){
            endDate = getMaxSecond(endDate);
        }
        String startDateString = date2String(startDate, null);
        String endDateString = date2String(endDate, null);
        for (Date middleDate:middleDates) {
            String middleDateString = date2String(middleDate, null);
            //相等也算在之间
            if((middleDate.after(startDate)||middleDateString.equals(startDateString)) && (middleDate.before(endDate)||middleDateString.equals(endDateString))){
                return true;
            }
        }
        return false;
    }

    /**
     * 根据指定日期获取之前num天的数据
     * num>0，获取之后的数据，num<0，获取之前的数据
     * num需要传
     * @param date
     * @param num
     * @param flag true:指定日期之前或之后的 00:00:00，false:指定日期之前或之后的 23:59:59。null:当前时间
     * @return
     */
    /**
     * 根据指定日期获取num天之前或之后的数据
     * @param date 日期
     * @param field 年月日，时分秒，例如：Calendar.DATE，Calendar.MONTH，Calendar.HOUR等
     * @param num num>0，获取之后的数据，num<0，获取之前的数据
     * @param flag true:指定日期之前或之后的 00:00:00，false:指定日期之前或之后的 23:59:59。null:当前时间
     * @param isOneDay true:指定日期之前或之后的 00:00:00，false:指定日期之前或之后的 23:59:59。null:当前时间
     * @return
     */
    public static String getBeforeLastAllStatusByDateNum(Date date,Integer field,Integer num,Boolean flag,Boolean isOneDay){
        if(Objects.isNull(date) || num==null || field==null){
            return null;
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(default_format);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(field,num);
        if(Objects.nonNull(isOneDay)){
            if(isOneDay){
                calendar.add(field, 0);
                calendar.set(Calendar.DAY_OF_MONTH, 1);
            }else {
                calendar.add(field, 1);
                calendar.set(Calendar.DAY_OF_MONTH, 0);
            }
        }
        if(Objects.nonNull(flag)){
            SimpleDateFormat yyyyMMdd = new SimpleDateFormat(yearMonthDayLine);
            if(flag){
                String firstDay = yyyyMMdd.format(calendar.getTime());
                firstDay = firstDay + " 00:00:00";
                return firstDay;
            }else {
                String lastDay = yyyyMMdd.format(calendar.getTime());
                lastDay = lastDay + " 23:59:59";
                return lastDay;
            }
        }
        return simpleDateFormat.format(calendar.getTime());
    }

    /**
     * 判断两个日期是否属于同一个月
     * @param firstDate
     * @param lastDate
     * @return
     */
    public static Boolean isSameMonth(Date firstDate,Date lastDate){
        Calendar calendar1 = Calendar.getInstance();
        calendar1.setTime(firstDate);
        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTime(lastDate);
        return calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR) && calendar1.get(Calendar.MONTH) == calendar2.get(Calendar.MONTH);
    }

    /**
     * 获取两个日期之间相差多少个月
     * @param startDate
     * @param endDate
     * @param isReset true:两个日期相差的月份，false:两个日期相差不满一个月时，则去掉该月，取整月
     * @return
     */
    public static Long getMonthSpace(Date startDate,Date endDate,Boolean isReset){
        if(startDate.after(endDate)){
            Date date = new Date();
            date.setTime(endDate.getTime());
            endDate.setTime(startDate.getTime());
            startDate.setTime(date.getTime());
        }
        Calendar beginCal = Calendar.getInstance();
        Calendar endCal = Calendar.getInstance();
        beginCal.setTime(startDate);
        endCal.setTime(endDate);
        int betweenYear = endCal.get(Calendar.YEAR) - beginCal.get(Calendar.YEAR);
        int betweenMonthOfYear = endCal.get(Calendar.MONTH) - beginCal.get(Calendar.MONTH);
        int result = betweenYear * 12 + betweenMonthOfYear;
        if (Objects.nonNull(isReset) && !isReset) {
            endCal.set(Calendar.YEAR, beginCal.get(Calendar.YEAR));
            endCal.set(Calendar.MONTH, beginCal.get(Calendar.MONTH));
            long between = endCal.getTimeInMillis() - beginCal.getTimeInMillis();
            if (between < 0L) {
                return (long)(result - 1);
            }
        }
        return (long)result;
    }

    /**
     * 根据类似时间字符串 2023-09-01T08:12:34.000+06:00 转换成Date类型 的标准时间
     * @param dateTimeString 入参时间字符串，支持如下5种格式。
     *                       格式为：2023-09-01T08:12:34.000+03:00 或 2023-09-01T08:12:34.000+0300 或 2023-09-01T08:12:34+0300 或 2023-09-01T08:12:34+03:00 或 2023-09-01T08:12:34Z
     * @return
     */
    public static Date getStandardDateTime(String dateTimeString){
        if(StringUtils.isBlank(dateTimeString)){
            return null;
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
        // 将字符串解析为 OffsetDateTime 对象
        OffsetDateTime offsetDateTime = null;
        LocalDateTime parse = null;
        try {
            parse = LocalDateTime.parse(dateTimeString, formatter);
        }catch (Exception e){
            try {
                offsetDateTime= OffsetDateTime.parse(dateTimeString, formatter);
            }catch (Exception ex){
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
                try {
                    Date parse1 = sdf.parse(dateTimeString);
                    return parse1;
                } catch (ParseException exc) {
                    //处理 2023-09-01T08:12:34.000+0800格式的数据
                    DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
                    try {
                        offsetDateTime= OffsetDateTime.parse(dateTimeString, outputFormatter);
                        String string1 = offsetDateTime.toString();
                        if(StringUtils.isNotBlank(string1) && string1.length()>6){
                            DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX");
                            OffsetDateTime of = OffsetDateTime.of(LocalDateTime.parse(string1, formatter1), OffsetDateTime.now().getOffset());
                            String string = of.toString();
                            if(string.length()>6){
                                // 解析时间字符串为 ZonedDateTime 对象
                                ZonedDateTime zonedDateTime = ZonedDateTime.parse(string, formatter1);
                                // 获取时区偏移量的总秒数
                                long totalSeconds = zonedDateTime.getOffset().getTotalSeconds();
                                // 将总秒数转换为分钟数
                                int offsetMinutes = (int) (totalSeconds / 60 / 60);
                                if(Objects.isNull(offsetDateTime)){
                                    offsetDateTime= OffsetDateTime.parse(string, formatter1);
                                }
                                // 转换为标准时间，这里假设标准时间为 UTC
                                OffsetDateTime utcDateTime = offsetDateTime.minusHours(offsetMinutes);
                                // 将转换后的 OffsetDateTime 转换为 LocalDateTime，然后转换为 Date 类型
                                Date date = Date.from(utcDateTime.toInstant());
                                // 输出转换后的 UTC 时间
                                return date;
                            }
                        }

                    }catch (Exception exce){
                        DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX");
                        OffsetDateTime of = null;
                        try {
                            of = OffsetDateTime.of(LocalDateTime.parse(dateTimeString, formatter1), OffsetDateTime.now().getOffset());
                        }catch (Exception excep){
                            DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ");
                            try {
                                offsetDateTime= OffsetDateTime.parse(dateTimeString, formatter2);
                            }catch (Exception except){
                                log.error("时间转换成标准格式错误入参为：{}",dateTimeString);
                                return null;
                            }
                            String string1 = offsetDateTime.toString();
                            if(StringUtils.isNotBlank(string1) && string1.length()>6){
                                OffsetDateTime of1 = OffsetDateTime.of(LocalDateTime.parse(string1, formatter1), OffsetDateTime.now().getOffset());
                                String string = of1.toString();
                                if(string.length()>6){
                                    // 解析时间字符串为 ZonedDateTime 对象
                                    ZonedDateTime zonedDateTime = ZonedDateTime.parse(string, formatter1);
                                    // 获取时区偏移量的总秒数
                                    long totalSeconds = zonedDateTime.getOffset().getTotalSeconds();
                                    // 将总秒数转换为分钟数
                                    int offsetMinutes = (int) (totalSeconds / 60 / 60);
                                    if(Objects.isNull(offsetDateTime)){
                                        offsetDateTime= OffsetDateTime.parse(string, formatter1);
                                    }
                                    // 转换为标准时间，这里假设标准时间为 UTC
                                    OffsetDateTime utcDateTime = offsetDateTime.minusHours(offsetMinutes);
                                    // 将转换后的 OffsetDateTime 转换为 LocalDateTime，然后转换为 Date 类型
                                    Date date = Date.from(utcDateTime.toInstant());
                                    // 输出转换后的 UTC 时间
                                    return date;
                                }
                            }
                            return null;
                        }
                        String string = of.toString();
                        if(string.length()>6){
                            // 解析时间字符串为 ZonedDateTime 对象
                            ZonedDateTime zonedDateTime = ZonedDateTime.parse(string, formatter1);
                            // 获取时区偏移量的总秒数
                            long totalSeconds = zonedDateTime.getOffset().getTotalSeconds();
                            // 将总秒数转换为分钟数
                            int offsetMinutes = (int) (totalSeconds / 60 / 60);
                            if(Objects.isNull(offsetDateTime)){
                                offsetDateTime= OffsetDateTime.parse(dateTimeString, formatter1);
                            }
                            // 转换为标准时间，这里假设标准时间为 UTC
                            OffsetDateTime utcDateTime = offsetDateTime.minusHours(offsetMinutes);
                            // 将转换后的 OffsetDateTime 转换为 LocalDateTime，然后转换为 Date 类型
                            Date date = Date.from(utcDateTime.toInstant());
                            // 输出转换后的 UTC 时间
                            return date;
                        }
                        return null;
                    }
                    return null;
                }
            }
        }
        OffsetDateTime of = OffsetDateTime.of(parse, OffsetDateTime.now().getOffset());
        String string = of.toString();
        if(string.length()>6){
            DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX");
            // 解析时间字符串为 ZonedDateTime 对象
            ZonedDateTime zonedDateTime = ZonedDateTime.parse(string, formatter1);
            // 获取时区偏移量的总秒数
            long totalSeconds = zonedDateTime.getOffset().getTotalSeconds();
            // 将总秒数转换为分钟数
            int offsetMinutes = (int) (totalSeconds / 60 / 60);
            if(Objects.isNull(offsetDateTime)){
                offsetDateTime= OffsetDateTime.parse(dateTimeString, formatter);
            }
            // 转换为标准时间，这里假设标准时间为 UTC
            OffsetDateTime utcDateTime = offsetDateTime.minusHours(offsetMinutes);
            // 将转换后的 OffsetDateTime 转换为 LocalDateTime，然后转换为 Date 类型
            Date date = Date.from(utcDateTime.toInstant());
            // 输出转换后的 UTC 时间
            return date;
        }
        return null;
    }
    /**
     * @Author hewenlong
     * @Description //获取当月第day天的时间戳
     * @Date 18:18 2023/10/20
     * @Param
     * @return java.lang.Long
     **/
    public static Long getDayOfMonth(int day){
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        // 设置为本月的day号
        LocalDate targetDate = currentDate.withDayOfMonth(day);
        // 将日期转换为时间戳（秒级）
        long timestamp = targetDate.atStartOfDay().toEpochSecond(ZoneOffset.UTC);
        return timestamp;
    }
    /**
     * @Author hewenlong
     * @Description //获取指定时间第n个月的时间，比如传入2023-10-20 18:20:15，获取2023-10-${day} 00:00:00的时间
     * @Date 18:19 2023/10/20
     * @Param
     * @return java.lang.Long
     **/
    public static Long getAnyDayOfMonth(int day, Date date){
        // Date转成LocalDate
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDate localDate = date.toInstant().atZone(zoneId).toLocalDate();
        // 设置为该月的day号
        LocalDate targetDate = localDate.withDayOfMonth(day);
        // 将日期转换为时间戳（秒级）
        long timestamp = targetDate.atStartOfDay().toEpochSecond(ZoneOffset.UTC);
        return timestamp;
    }

    /**
     * 获取两个日期相差的天数,如果某个日期为空,则获取当前日期和传入日期的相差天数.
     * @param startDate
     * @param endDate
     * @param flag 为true时,算上首尾当天
     * @return
     */
    public static Long getMiddleDays(Date startDate,Date endDate,Boolean flag){
        if(Objects.isNull(startDate) || Objects.isNull(endDate)){
            // 获取当前日期
            LocalDate currentDate = LocalDate.now();
            if(Objects.isNull(startDate) && Objects.nonNull(endDate)){
                LocalDate localDate = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                long days = ChronoUnit.DAYS.between(currentDate, localDate);
                return Math.abs(days);
            }else if(Objects.nonNull(startDate) && Objects.isNull(endDate)){
                LocalDate localDate = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                long days = ChronoUnit.DAYS.between(currentDate, localDate);
                return Math.abs(days);
            }
            return 0L;
        }
        if(Objects.nonNull(flag) && flag){
            LocalDate date1 = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            LocalDate date2 = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            long days = ChronoUnit.DAYS.between(date1, date2);
            return Math.abs(days)+1;
        }
        LocalDate date1 = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate date2 = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        long days = ChronoUnit.DAYS.between(date1, date2);
        return Math.abs(days);
    }


    /**
     * 获取自然日时长
     * @param startDate 自然日开始时间
     * @param endDate 自然日结束时间
     * @param morningStartDate 上午上班打卡时间
     * @param morningEndDate 上午下班打卡时间
     * @param afternoonStartDate 下午上班打卡时间
     * @param afternoonEndDate 下午下班打卡时间
     * @param morningHour 上午假期时长间隔
     * @param afternoonHour 下午请假时长间隔
     * @return
     * @throws ParseException
     */
    public static BigDecimal getNaturalDayAttendance(Date startDate,Date endDate,Date morningStartDate,Date morningEndDate,Date afternoonStartDate,Date afternoonEndDate,BigDecimal morningHour,BigDecimal afternoonHour){
        if(Objects.isNull(startDate) || Objects.isNull(endDate)){
            return BigDecimal.ZERO;
        }
        if(startDate.after(endDate)){
            Date date = new Date();
            date.setTime(endDate.getTime());
            endDate.setTime(startDate.getTime());
            startDate.setTime(date.getTime());
        }
        //dateList：自然日
        List<Date> dateBetween = getDateBetween(startDate, endDate, true, true);
        List<String> dateBetweenString = null;
        if(CollectionUtils.isNotEmpty(dateBetween)){
            dateBetweenString = dateBetween.stream().map(x->date2String(x,yearMonthDayLine)).collect(Collectors.toList());
        }
        if(CollectionUtils.isEmpty(dateBetweenString)){
            return BigDecimal.ZERO;
        }
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat(yearMonthDayLine);

        List<String> yyyyMMddString = new ArrayList<>();
        for (String d:dateBetweenString) {
            yyyyMMddString.add(d);
        }
        String format = yyyyMMdd.format(startDate);
        String format1 = yyyyMMdd.format(endDate);

        //请假是在同一天
        if(format.equals(format1)){
            if(yyyyMMddString.contains(format)){
                BigDecimal total = BigDecimal.ZERO;
                Date dateMorningStart = joinDateAndTime(startDate, morningStartDate);
                Date dateMorningEnd = joinDateAndTime(startDate, morningEndDate);
                Date dateAfternoonStart = joinDateAndTime(startDate, afternoonStartDate);
                Date dateAfternoonEnd = joinDateAndTime(startDate, afternoonEndDate);
                //上午请假
                if(sqlTimeEquals(startDate,dateMorningStart) && sqlTimeEquals(endDate,dateMorningEnd)){
                    total = total.add(morningHour);
                }else if(sqlTimeEquals(startDate,dateMorningStart) && sqlTimeEquals(endDate,dateAfternoonEnd)){
                    //全天请假
                    total = total.add(morningHour).add(afternoonHour);
                }else if(sqlTimeEquals(startDate,dateAfternoonStart) && sqlTimeEquals(endDate,dateAfternoonEnd)){
                    //下午请假
                    total = total.add(afternoonHour);
                }
                total = total.setScale(2,BigDecimal.ROUND_HALF_UP);
                return total;
            }
            return BigDecimal.ZERO;
        }else {
            Calendar clCalendar=Calendar.getInstance();
            clCalendar.setTime(startDate);
            clCalendar.add(Calendar.DATE, 1);
            String format2 = yyyyMMdd.format(clCalendar.getTime());
            //请假是相邻天
            if (format1.equals(format2)){
                Date morningStart = joinDateAndTime(startDate, morningStartDate);
                Date afternoonStart = joinDateAndTime(startDate, afternoonStartDate);
                Date morningEnd1 = joinDateAndTime(endDate, morningEndDate);
                Date afternoonEnd1 = joinDateAndTime(endDate, afternoonEndDate);
                BigDecimal total = BigDecimal.ZERO;
                //请假的两天都在工作日内
                //请假两天
                if(sqlTimeEquals(startDate,morningStart) && sqlTimeEquals(endDate,afternoonEnd1)){
                    total = (total.add(morningHour).add(afternoonHour)).multiply(new BigDecimal("2"));
                }else if(sqlTimeEquals(startDate,morningStart) && sqlTimeEquals(endDate,morningEnd1)){
                    //第一天请假一天，第二天请假半天
                    total = total.add(morningHour).add(morningHour).add(afternoonHour);
                }else if(sqlTimeEquals(startDate,afternoonStart) && sqlTimeEquals(endDate,afternoonEnd1)){
                    //第一天请假半天，第二天请假一天
                    total = total.add(morningHour).add(afternoonHour).add(afternoonHour);
                }else if(sqlTimeEquals(startDate,afternoonStart) && sqlTimeEquals(endDate,morningEnd1)){
                    //第一天请假半天，第二天请假半天
                    total = total.add(morningHour).add(afternoonHour);
                }
                total = total.setScale(2,BigDecimal.ROUND_HALF_UP);
                return total;
            }else {
                //存在跨天的情况
                Date morningStart = joinDateAndTime(startDate, morningStartDate);
                Date afternoonStart = joinDateAndTime(startDate, afternoonStartDate);
                Date morningEnd1 = joinDateAndTime(endDate, morningEndDate);
                Date afternoonEnd1 = joinDateAndTime(endDate, afternoonEndDate);
                int size = yyyyMMddString.size();
                BigDecimal total = BigDecimal.ZERO;
                // 例 周六请假 到周一上午，实际请假只有周一上午半天
                if(size>2){
                    BigDecimal hours = (morningHour.add(afternoonHour)).multiply(new BigDecimal(String.valueOf(size-2)));
                    //请假两天
                    if(sqlTimeEquals(startDate,morningStart) && sqlTimeEquals(endDate,afternoonEnd1)){
                        total = (total.add(morningHour).add(afternoonHour)).multiply(new BigDecimal("2")).add(hours);
                    }else if(sqlTimeEquals(startDate,morningStart) && sqlTimeEquals(endDate,morningEnd1)){
                        //第一天请假一天，第二天请假半天
                        total = total.add(morningHour).add(morningHour).add(afternoonHour).add(hours);
                    }else if(sqlTimeEquals(startDate,afternoonStart) && sqlTimeEquals(endDate,afternoonEnd1)){
                        //第一天请假半天，第二天请假一天
                        total = total.add(morningHour).add(afternoonHour).add(afternoonHour).add(hours);
                    }else if(sqlTimeEquals(startDate,afternoonStart) && sqlTimeEquals(endDate,morningEnd1)){
                        //第一天请假半天，第二天请假半天
                        total = total.add(morningHour).add(afternoonHour).add(hours);
                    }
                }
                total = total.setScale(2,BigDecimal.ROUND_HALF_UP);
                return total;
            }
        }
    }

    /**
     * 获取自然日时长
     * @param startDate 自然日开始时间,随机时间点
     * @param endDate 自然日结束时间,随机时间点
     * @param morningStartDate 上午上班打卡时间
     * @param morningEndDate 上午下班打卡时间
     * @param afternoonStartDate 下午上班打卡时间
     * @param afternoonEndDate 下午下班打卡时间
     * @param morningHour 上午假期时长间隔
     * @param afternoonHour 下午请假时长间隔
     * @return
     * @throws ParseException
     */
    public static BigDecimal getNaturalDayRandomDatePoint(Date startDate,Date endDate,Date morningStartDate,Date morningEndDate,Date afternoonStartDate,Date afternoonEndDate,BigDecimal morningHour,BigDecimal afternoonHour){
        if(Objects.isNull(startDate) || Objects.isNull(endDate)){
            return BigDecimal.ZERO;
        }
        if(startDate.after(endDate)){
            Date date = new Date();
            date.setTime(endDate.getTime());
            endDate.setTime(startDate.getTime());
            startDate.setTime(date.getTime());
        }
        //dateList：自然日
        List<Date> dateBetween = getDateBetween(startDate, endDate, true, true);
        List<String> dateBetweenString = null;
        if(CollectionUtils.isNotEmpty(dateBetween)){
            dateBetweenString = dateBetween.stream().map(x->date2String(x,yearMonthDayLine)).collect(Collectors.toList());
        }
        if(CollectionUtils.isEmpty(dateBetweenString)){
            return BigDecimal.ZERO;
        }
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat(yearMonthDayLine);

        List<String> yyyyMMddString = new ArrayList<>();
        for (String d:dateBetweenString) {
            yyyyMMddString.add(d);
        }
        String format = yyyyMMdd.format(startDate);
        String format1 = yyyyMMdd.format(endDate);

        Date morningStart = joinDateAndTime(startDate, morningStartDate);
        Date morningEnd = joinDateAndTime(startDate, morningEndDate);
        Date afternoonStart = joinDateAndTime(startDate, afternoonStartDate);
        Date afternoonEnd = joinDateAndTime(startDate, afternoonEndDate);
        Date morningStart1 = joinDateAndTime(endDate, morningStartDate);
        Date morningEnd1 = joinDateAndTime(endDate, morningEndDate);
        Date afternoonStart1 = joinDateAndTime(endDate, afternoonStartDate);
        Date afternoonEnd1 = joinDateAndTime(endDate, afternoonEndDate);
        //请假是在同一天
        if(format.equals(format1)){
            if(yyyyMMddString.contains(format)){
                //理论上 存在15种 情况
                BigDecimal total = BigDecimal.ZERO;
                //都在开始日期之前 或者 都在中午休息时间 或者 都在下班时间之后
                if((dateBeforeLessThan(startDate,morningStart) && dateBeforeLessThan(endDate,morningStart1))
                        || (dateBeforeLessThan(startDate,afternoonStart) && dateAfterLessThan(startDate,morningEnd)
                            && dateBeforeLessThan(endDate,afternoonStart1) && dateAfterLessThan(endDate,morningEnd1))
                        || ((dateAfterLessThan(startDate,afternoonEnd) || startDate.getTime() == afternoonEnd.getTime())
                            && (dateAfterLessThan(endDate,afternoonEnd1) || endDate.getTime() == afternoonEnd1.getTime()))){
                }else if(dateBeforeLessThan(startDate,morningStart)
                        && dateBeforeLessThan(endDate,morningEnd1) && dateAfterLessThan(endDate,morningStart1)){
                    //开始日期在上班前,结束日期在上午上班后,上午下班前
                    BigDecimal bigDecimal = dateSubtractionDate(morningStart, endDate, DateTimeEnum.Hour);
                    total = total.add(bigDecimal);
                }else if(dateBeforeLessThan(startDate,morningStart)
                        && dateBeforeLessThan(endDate,afternoonStart1) && dateAfterLessThan(endDate,morningEnd1)){
                    //开始日期在上班前,结束日期在上午下班后,下午上班前
                    total = total.add(morningHour);
                }else if(dateBeforeLessThan(startDate,morningStart)
                        && dateBeforeLessThan(endDate,afternoonEnd1) && dateAfterLessThan(endDate,afternoonStart1)){
                    //开始日期在上班前,结束日期在下午上班后,下班下班前
                    BigDecimal bigDecimal = dateSubtractionDate(afternoonStart1, endDate, DateTimeEnum.Hour);
                    total = total.add(bigDecimal).add(morningHour);
                }else if(dateBeforeLessThan(startDate,morningStart)
                        && (dateAfterLessThan(endDate,afternoonEnd1) || endDate.getTime()==afternoonEnd1.getTime())){
                    //开始在上班前,结束在下班后
                    total = total.add(morningHour).add(afternoonHour);
                }else if(dateAfterLessThan(startDate,morningStart) && dateBeforeLessThan(startDate,morningEnd)
                        && dateBeforeLessThan(endDate,morningEnd1) && dateAfterLessThan(endDate,morningStart1)){
                    //开始在上午上班后,上午下班前,结束在上午上班后,上午下班前
                    BigDecimal bigDecimal = dateSubtractionDate(startDate, endDate, DateTimeEnum.Hour);
                    total = total.add(bigDecimal);
                } else if (dateAfterLessThan(startDate,morningStart) && dateBeforeLessThan(startDate,morningEnd)
                        && dateBeforeLessThan(endDate,afternoonStart1) && dateAfterLessThan(endDate,morningEnd1)) {
                    //开始在上午上班后,上午下班前,结束在上午下班后,下午上班前
                    BigDecimal bigDecimal = dateSubtractionDate(startDate, morningEnd, DateTimeEnum.Hour);
                    total = total.add(bigDecimal);
                } else if (dateAfterLessThan(startDate, morningStart) && dateBeforeLessThan(startDate, morningEnd)
                        && dateBeforeLessThan(endDate, afternoonEnd1) && dateAfterLessThan(endDate, afternoonStart1)) {
                    //开始在上午上班后，上午下班前；结束在下午上班后，下午下班前
                    BigDecimal bigDecimal = dateSubtractionDate(startDate, morningEnd, DateTimeEnum.Hour);
                    BigDecimal decimal = dateSubtractionDate(afternoonStart1, endDate, DateTimeEnum.Hour);
                    total = total.add(bigDecimal).add(decimal);
                } else if (dateAfterLessThan(startDate, morningStart) && dateBeforeLessThan(startDate, morningEnd)
                        && (dateAfterLessThan(endDate,afternoonEnd1) || endDate.getTime() == afternoonEnd1.getTime())) {
                    //开始在上午上班后，上午下班前，结束在下午下班后
                    BigDecimal bigDecimal = dateSubtractionDate(startDate, morningEnd, DateTimeEnum.Hour);
                    total = total.add(bigDecimal).add(afternoonHour);
                } else if (dateAfterLessThan(startDate, morningEnd) && dateBeforeLessThan(startDate, afternoonStart1)
                        && dateBeforeLessThan(endDate, afternoonEnd1) && dateAfterLessThan(endDate, afternoonStart1)) {
                    //开始在上午下班后，下午上班前（中午休息时间），结束在下午上班后，下午下班前
                    BigDecimal bigDecimal = dateSubtractionDate(afternoonStart1, endDate, DateTimeEnum.Hour);
                    total = total.add(bigDecimal);
                } else if (dateAfterLessThan(startDate, morningEnd) && dateBeforeLessThan(startDate, afternoonStart1)
                        && (dateAfterLessThan(endDate,afternoonEnd1) || endDate.getTime() == afternoonEnd1.getTime())) {
                    //开始在上午下班后，下午上班前（中午休息时间），结束在下午下班后
                    total = total.add(afternoonHour);
                } else if (dateAfterLessThan(startDate, afternoonStart) && dateBeforeLessThan(startDate, afternoonEnd)
                        && dateAfterLessThan(endDate, afternoonStart1) && dateBeforeLessThan(endDate, afternoonEnd1)) {
                    //开始在下午上班后，下午下班前，结束在下午上班后，下班下班前
                    BigDecimal bigDecimal = dateSubtractionDate(startDate, endDate, DateTimeEnum.Hour);
                    total = total.add(bigDecimal);
                } else if (dateAfterLessThan(startDate, afternoonStart) && dateBeforeLessThan(startDate, afternoonEnd)
                        && (dateAfterLessThan(endDate, afternoonEnd1) || endDate.getTime() == afternoonEnd1.getTime())) {
                    //开始在下午上班后，下午下班前，结束在下午下班后
                    BigDecimal bigDecimal = dateSubtractionDate(startDate, afternoonEnd1, DateTimeEnum.Hour);
                    total = total.add(bigDecimal);
                } else {
                    log.info("DateTimeUtil_getNaturalDayRandomDatePoint_error_sameDay {},{}",JSONObject.toJSONString(startDate),JSONObject.toJSONString(endDate));
                }
                total = total.setScale(2,BigDecimal.ROUND_HALF_UP);
                return total;
            }
            return BigDecimal.ZERO;
        }else {
            Calendar clCalendar=Calendar.getInstance();
            clCalendar.setTime(startDate);
            clCalendar.add(Calendar.DATE, 1);
            String format2 = yyyyMMdd.format(clCalendar.getTime());
            //相邻的两天
            if (format1.equals(format2)){
                // 理论上存在 25 种情况
                BigDecimal total = BigDecimal.ZERO;
                //开始是在下午下班结束后，结束是在第二天上班开始前 。 为 0
                if((dateAfterLessThan(startDate,afternoonEnd) || startDate.getTime() == afternoonEnd.getTime())
                        && dateBeforeLessThan(endDate,morningStart1)){
                }else if(dateBeforeLessThan(startDate,morningStart)
                        && dateBeforeLessThan(endDate,morningStart1)){
                    //开始日期在上班前,结束日期在上午上班前 。相邻天，就是只有一天
                    total = total.add(morningHour).add(afternoonHour);
                }else if(dateBeforeLessThan(startDate,morningStart)
                        && dateBeforeLessThan(endDate,morningEnd1) && dateAfterLessThan(endDate,morningStart1)){
                    //开始日期在上班前,结束日期在上午上班后,上午下班前
                    BigDecimal bigDecimal = dateSubtractionDate(morningStart1, endDate, DateTimeEnum.Hour);
                    total = total.add(morningHour).add(afternoonHour).add(bigDecimal);
                }else if(dateBeforeLessThan(startDate,morningStart)
                        && dateBeforeLessThan(endDate,afternoonStart1) && dateAfterLessThan(endDate,morningEnd1)){
                    //开始日期在上班前,结束日期在上午下班后,下午上班前
                    total = total.add(morningHour).add(afternoonHour).add(morningHour);
                }else if(dateBeforeLessThan(startDate,morningStart)
                        && dateBeforeLessThan(endDate,afternoonEnd1) && dateAfterLessThan(endDate,afternoonStart1)){
                    //开始日期在上班前,结束日期在下午上班后,下班下班前
                    BigDecimal bigDecimal = dateSubtractionDate(afternoonStart1, endDate, DateTimeEnum.Hour);
                    total = total.add(bigDecimal).add(morningHour).add(morningHour).add(afternoonHour);
                }else if(dateBeforeLessThan(startDate,morningStart)
                        && (dateAfterLessThan(endDate,afternoonEnd1) || endDate.getTime()==afternoonEnd1.getTime())){
                    //开始在上班前,结束在下班后
                    total = total.add(morningHour).add(afternoonHour).add(morningHour).add(afternoonHour);
                }
                // 开始在上午上班后，上午下班前，结束在第二天的随意时间点
                else if(dateAfterLessThan(startDate,morningStart) && dateBeforeLessThan(startDate,morningEnd)
                        && dateBeforeLessThan(endDate,morningStart1)){
                    //开始在上午上班后,上午下班前,结束在上午上班前
                    BigDecimal bigDecimal = dateSubtractionDate(startDate, morningEnd, DateTimeEnum.Hour);
                    total = total.add(bigDecimal).add(afternoonHour);
                } else if(dateAfterLessThan(startDate,morningStart) && dateBeforeLessThan(startDate,morningEnd)
                        && dateBeforeLessThan(endDate,morningEnd1) && dateAfterLessThan(endDate,morningStart1)){
                    //开始在上午上班后,上午下班前,结束在上午上班后,上午下班前
                    BigDecimal bigDecimal = dateSubtractionDate(startDate, morningEnd, DateTimeEnum.Hour);
                    BigDecimal decimal = dateSubtractionDate(morningStart1, endDate, DateTimeEnum.Hour);
                    total = total.add(bigDecimal).add(afternoonHour).add(decimal);
                } else if (dateAfterLessThan(startDate,morningStart) && dateBeforeLessThan(startDate,morningEnd)
                        && dateBeforeLessThan(endDate,afternoonStart1) && dateAfterLessThan(endDate,morningEnd1)) {
                    //开始在上午上班后,上午下班前,结束在上午下班后,下午上班前
                    BigDecimal bigDecimal = dateSubtractionDate(startDate, morningEnd, DateTimeEnum.Hour);
                    total = total.add(bigDecimal).add(afternoonHour).add(morningHour);
                } else if (dateAfterLessThan(startDate, morningStart) && dateBeforeLessThan(startDate, morningEnd)
                        && dateBeforeLessThan(endDate, afternoonEnd1) && dateAfterLessThan(endDate, afternoonStart1)) {
                    //开始在上午上班后，上午下班前；结束在下午上班后，下午下班前
                    BigDecimal bigDecimal = dateSubtractionDate(startDate, morningEnd, DateTimeEnum.Hour);
                    BigDecimal decimal = dateSubtractionDate(afternoonStart1, endDate, DateTimeEnum.Hour);
                    total = total.add(bigDecimal).add(afternoonHour).add(decimal).add(morningHour);
                } else if (dateAfterLessThan(startDate, morningStart) && dateBeforeLessThan(startDate, morningEnd)
                        && (dateAfterLessThan(endDate,afternoonEnd1) || endDate.getTime() == afternoonEnd1.getTime())) {
                    //开始在上午上班后，上午下班前，结束在下午下班后
                    BigDecimal bigDecimal = dateSubtractionDate(startDate, morningEnd, DateTimeEnum.Hour);
                    total = total.add(bigDecimal).add(afternoonHour).add(morningHour).add(afternoonHour);
                }
                //开始时间在中午休息时间，结束时间在第二天随意时间点
                else if (dateAfterLessThan(startDate, morningEnd) && dateBeforeLessThan(startDate, afternoonStart1)
                        && dateBeforeLessThan(endDate,morningStart1)) {
                    //开始在上午下班后，下午上班前（中午休息时间），结束在上午上班后，
                    total = total.add(afternoonHour);
                }
                else if (dateAfterLessThan(startDate, morningEnd) && dateBeforeLessThan(startDate, afternoonStart1)
                        && dateBeforeLessThan(endDate,morningEnd1) && dateAfterLessThan(endDate,morningStart1)) {
                    //开始在上午下班后，下午上班前（中午休息时间），结束在上午上班后，上午下班前
                    BigDecimal bigDecimal = dateSubtractionDate(afternoonStart1, endDate, DateTimeEnum.Hour);
                    total = total.add(afternoonHour).add(bigDecimal);
                }
                else if (dateAfterLessThan(startDate, morningEnd) && dateBeforeLessThan(startDate, afternoonStart1)
                        && dateBeforeLessThan(endDate,afternoonStart1) && dateAfterLessThan(endDate,morningEnd1)) {
                    //开始在上午下班后，下午上班前（中午休息时间），结束在下午上班前，上午下班后（中午休息时间）
                    total = total.add(afternoonHour).add(morningHour);
                }
                else if (dateAfterLessThan(startDate, morningEnd) && dateBeforeLessThan(startDate, afternoonStart1)
                        && dateBeforeLessThan(endDate, afternoonEnd1) && dateAfterLessThan(endDate, afternoonStart1)) {
                    //开始在上午下班后，下午上班前（中午休息时间），结束在下午上班后，下午下班前
                    BigDecimal bigDecimal = dateSubtractionDate(afternoonStart1, endDate, DateTimeEnum.Hour);
                    total = total.add(afternoonHour).add(morningHour).add(bigDecimal);
                } else if (dateAfterLessThan(startDate, morningEnd) && dateBeforeLessThan(startDate, afternoonStart1)
                        && (dateAfterLessThan(endDate,afternoonEnd1) || endDate.getTime() == afternoonEnd1.getTime())) {
                    //开始在上午下班后，下午上班前（中午休息时间），结束在下午下班后
                    total = total.add(afternoonHour).add(morningHour).add(afternoonHour);
                }
                //开始时间在下午上班后，下午下班前，结束时间在第二天随意时间点
                else if (dateAfterLessThan(startDate, afternoonStart) && dateBeforeLessThan(startDate, afternoonEnd)
                        && dateBeforeLessThan(endDate,morningStart1)) {
                    //开始在下午上班后，下午下班前，结束在上午上班前
                    BigDecimal bigDecimal = dateSubtractionDate(startDate, afternoonEnd, DateTimeEnum.Hour);
                    total = total.add(bigDecimal);
                }
                else if (dateAfterLessThan(startDate, afternoonStart) && dateBeforeLessThan(startDate, afternoonEnd)
                        && dateBeforeLessThan(endDate,morningEnd1) && dateAfterLessThan(endDate,morningStart1)) {
                    //开始在下午上班后，下午下班前，结束在下午上班后，上午下班前
                    BigDecimal bigDecimal = dateSubtractionDate(startDate, afternoonEnd, DateTimeEnum.Hour);
                    BigDecimal decimal = dateSubtractionDate(morningStart1, endDate, DateTimeEnum.Hour);
                    total = total.add(bigDecimal).add(decimal);
                }else if (dateAfterLessThan(startDate, afternoonStart) && dateBeforeLessThan(startDate, afternoonEnd)
                        && dateBeforeLessThan(endDate,afternoonStart1) && dateAfterLessThan(endDate,morningEnd1)) {
                    //开始在下午上班后，下午下班前，结束在下午上班前，上午下班后（中午休息时间）
                    BigDecimal bigDecimal = dateSubtractionDate(startDate, afternoonEnd, DateTimeEnum.Hour);
                    total = total.add(bigDecimal).add(morningHour);
                }else if (dateAfterLessThan(startDate, afternoonStart) && dateBeforeLessThan(startDate, afternoonEnd)
                        && dateAfterLessThan(endDate, afternoonStart1) && dateBeforeLessThan(endDate, afternoonEnd1)) {
                    //开始在下午上班后，下午下班前，结束在下午上班后，下班下班前
                    BigDecimal bigDecimal = dateSubtractionDate(startDate, afternoonEnd, DateTimeEnum.Hour);
                    BigDecimal decimal = dateSubtractionDate(afternoonStart1, endDate, DateTimeEnum.Hour);
                    total = total.add(bigDecimal).add(morningHour).add(decimal);
                } else if (dateAfterLessThan(startDate, afternoonStart) && dateBeforeLessThan(startDate, afternoonEnd)
                        && (dateAfterLessThan(endDate, afternoonEnd1) || endDate.getTime() == afternoonEnd1.getTime())) {
                    //开始在下午上班后，下午下班前，结束在下午下班后
                    BigDecimal bigDecimal = dateSubtractionDate(startDate, afternoonEnd, DateTimeEnum.Hour);
                    total = total.add(bigDecimal).add(morningHour).add(afternoonHour);
                }
                //开始时间在下午下班后，结束时间在第二天随意时间点
                else if ((dateAfterLessThan(startDate,afternoonEnd) || startDate.getTime() == afternoonEnd.getTime())
                        && dateBeforeLessThan(endDate,morningStart1)) {
                    //开始时间在下午下班后，结束时间在上午上班前
                }else if ((dateAfterLessThan(startDate,afternoonEnd) || startDate.getTime() == afternoonEnd.getTime())
                        && dateBeforeLessThan(endDate,morningEnd1) && dateAfterLessThan(endDate,morningStart1)) {
                    //开始时间在下午下班后，结束时间在上午上班后，上午下班前
                    BigDecimal bigDecimal = dateSubtractionDate(morningStart1, endDate, DateTimeEnum.Hour);
                    total = total.add(bigDecimal);
                }else if ((dateAfterLessThan(startDate,afternoonEnd) || startDate.getTime() == afternoonEnd.getTime())
                        && dateBeforeLessThan(endDate,afternoonStart1) && dateAfterLessThan(endDate,morningEnd1)) {
                    //开始时间在下午下班后，结束时间在上午下班后，下午上班前（中午休息时间）
                    total = total.add(morningHour);
                }else if ((dateAfterLessThan(startDate,afternoonEnd) || startDate.getTime() == afternoonEnd.getTime())
                        && dateAfterLessThan(endDate, afternoonStart1) && dateBeforeLessThan(endDate, afternoonEnd1)) {
                    //开始时间在下午下班后，结束时间在下午上班后，下午下班前
                    BigDecimal bigDecimal = dateSubtractionDate(afternoonStart1, endDate, DateTimeEnum.Hour);
                    total = total.add(morningHour).add(bigDecimal);
                }else if ((dateAfterLessThan(startDate,afternoonEnd) || startDate.getTime() == afternoonEnd.getTime())
                        && (dateAfterLessThan(endDate, afternoonEnd1) || endDate.getTime() == afternoonEnd1.getTime())) {
                    //开始时间在下午下班后，结束时间在下午下班后
                    total = total.add(morningHour).add(afternoonHour);
                }else {
                    log.info("DateTimeUtil_getNaturalDayRandomDatePoint_error_same2Day {},{}",JSONObject.toJSONString(startDate),JSONObject.toJSONString(endDate));
                }
                total = total.setScale(2,BigDecimal.ROUND_HALF_UP);
                return total;
            }else {
                //存在跨天的情况
                int size = yyyyMMddString.size();
                if(size>2){
                    BigDecimal total = BigDecimal.ZERO;
                    BigDecimal hours = (morningHour.add(afternoonHour)).multiply(new BigDecimal(String.valueOf(size-2)));

                    if(dateBeforeLessThan(startDate,morningStart)
                            && dateBeforeLessThan(endDate,morningStart1)){
                        //开始日期在上班前,结束日期在上午上班前 。相邻天，就是只有一天
                        total = total.add(morningHour).add(afternoonHour).add(hours);
                    }else if(dateBeforeLessThan(startDate,morningStart)
                            && dateBeforeLessThan(endDate,morningEnd1) && dateAfterLessThan(endDate,morningStart1)){
                        //开始日期在上班前,结束日期在上午上班后,上午下班前
                        BigDecimal bigDecimal = dateSubtractionDate(morningStart1, endDate, DateTimeEnum.Hour);
                        total = total.add(morningHour).add(afternoonHour).add(bigDecimal).add(hours);
                    }else if(dateBeforeLessThan(startDate,morningStart)
                            && dateBeforeLessThan(endDate,afternoonStart1) && dateAfterLessThan(endDate,morningEnd1)){
                        //开始日期在上班前,结束日期在上午下班后,下午上班前
                        total = total.add(morningHour).add(afternoonHour).add(morningHour).add(hours);
                    }else if(dateBeforeLessThan(startDate,morningStart)
                            && dateBeforeLessThan(endDate,afternoonEnd1) && dateAfterLessThan(endDate,afternoonStart1)){
                        //开始日期在上班前,结束日期在下午上班后,下班下班前
                        BigDecimal bigDecimal = dateSubtractionDate(afternoonStart1, endDate, DateTimeEnum.Hour);
                        total = total.add(bigDecimal).add(morningHour).add(morningHour).add(afternoonHour).add(hours);
                    }else if(dateBeforeLessThan(startDate,morningStart)
                            && (dateAfterLessThan(endDate,afternoonEnd1) || endDate.getTime()==afternoonEnd1.getTime())){
                        //开始在上班前,结束在下班后
                        total = total.add(morningHour).add(afternoonHour).add(morningHour).add(afternoonHour).add(hours);
                    }
                    // 开始在上午上班后，上午下班前，结束在第二天的随意时间点
                    else if(dateAfterLessThan(startDate,morningStart) && dateBeforeLessThan(startDate,morningEnd)
                            && dateBeforeLessThan(endDate,morningStart1)){
                        //开始在上午上班后,上午下班前,结束在上午上班前
                        BigDecimal bigDecimal = dateSubtractionDate(startDate, morningEnd, DateTimeEnum.Hour);
                        total = total.add(bigDecimal).add(afternoonHour).add(hours);
                    } else if(dateAfterLessThan(startDate,morningStart) && dateBeforeLessThan(startDate,morningEnd)
                            && dateBeforeLessThan(endDate,morningEnd1) && dateAfterLessThan(endDate,morningStart1)){
                        //开始在上午上班后,上午下班前,结束在上午上班后,上午下班前
                        BigDecimal bigDecimal = dateSubtractionDate(startDate, morningEnd, DateTimeEnum.Hour);
                        BigDecimal decimal = dateSubtractionDate(morningStart1, endDate, DateTimeEnum.Hour);
                        total = total.add(bigDecimal).add(afternoonHour).add(decimal).add(hours);
                    } else if (dateAfterLessThan(startDate,morningStart) && dateBeforeLessThan(startDate,morningEnd)
                            && dateBeforeLessThan(endDate,afternoonStart1) && dateAfterLessThan(endDate,morningEnd1)) {
                        //开始在上午上班后,上午下班前,结束在上午下班后,下午上班前
                        BigDecimal bigDecimal = dateSubtractionDate(startDate, morningEnd, DateTimeEnum.Hour);
                        total = total.add(bigDecimal).add(afternoonHour).add(morningHour).add(hours);
                    } else if (dateAfterLessThan(startDate, morningStart) && dateBeforeLessThan(startDate, morningEnd)
                            && dateBeforeLessThan(endDate, afternoonEnd1) && dateAfterLessThan(endDate, afternoonStart1)) {
                        //开始在上午上班后，上午下班前；结束在下午上班后，下午下班前
                        BigDecimal bigDecimal = dateSubtractionDate(startDate, morningEnd, DateTimeEnum.Hour);
                        BigDecimal decimal = dateSubtractionDate(afternoonStart1, endDate, DateTimeEnum.Hour);
                        total = total.add(bigDecimal).add(afternoonHour).add(decimal).add(morningHour).add(hours);
                    } else if (dateAfterLessThan(startDate, morningStart) && dateBeforeLessThan(startDate, morningEnd)
                            && (dateAfterLessThan(endDate,afternoonEnd1) || endDate.getTime() == afternoonEnd1.getTime())) {
                        //开始在上午上班后，上午下班前，结束在下午下班后
                        BigDecimal bigDecimal = dateSubtractionDate(startDate, morningEnd, DateTimeEnum.Hour);
                        total = total.add(bigDecimal).add(afternoonHour).add(morningHour).add(afternoonHour).add(hours);
                    }
                    //开始时间在中午休息时间，结束时间在第二天随意时间点
                    else if (dateAfterLessThan(startDate, morningEnd) && dateBeforeLessThan(startDate, afternoonStart1)
                            && dateBeforeLessThan(endDate,morningStart1)) {
                        //开始在上午下班后，下午上班前（中午休息时间），结束在上午上班后，
                        total = total.add(afternoonHour).add(hours);
                    }
                    else if (dateAfterLessThan(startDate, morningEnd) && dateBeforeLessThan(startDate, afternoonStart1)
                            && dateBeforeLessThan(endDate,morningEnd1) && dateAfterLessThan(endDate,morningStart1)) {
                        //开始在上午下班后，下午上班前（中午休息时间），结束在上午上班后，上午下班前
                        BigDecimal bigDecimal = dateSubtractionDate(afternoonStart1, endDate, DateTimeEnum.Hour);
                        total = total.add(afternoonHour).add(bigDecimal).add(hours);
                    }
                    else if (dateAfterLessThan(startDate, morningEnd) && dateBeforeLessThan(startDate, afternoonStart1)
                            && dateBeforeLessThan(endDate,afternoonStart1) && dateAfterLessThan(endDate,morningEnd1)) {
                        //开始在上午下班后，下午上班前（中午休息时间），结束在下午上班前，上午下班后（中午休息时间）
                        total = total.add(afternoonHour).add(morningHour).add(hours);
                    }
                    else if (dateAfterLessThan(startDate, morningEnd) && dateBeforeLessThan(startDate, afternoonStart1)
                            && dateBeforeLessThan(endDate, afternoonEnd1) && dateAfterLessThan(endDate, afternoonStart1)) {
                        //开始在上午下班后，下午上班前（中午休息时间），结束在下午上班后，下午下班前
                        BigDecimal bigDecimal = dateSubtractionDate(afternoonStart1, endDate, DateTimeEnum.Hour);
                        total = total.add(afternoonHour).add(morningHour).add(bigDecimal).add(hours);
                    } else if (dateAfterLessThan(startDate, morningEnd) && dateBeforeLessThan(startDate, afternoonStart1)
                            && (dateAfterLessThan(endDate,afternoonEnd1) || endDate.getTime() == afternoonEnd1.getTime())) {
                        //开始在上午下班后，下午上班前（中午休息时间），结束在下午下班后
                        total = total.add(afternoonHour).add(morningHour).add(afternoonHour).add(hours);
                    }
                    //开始时间在下午上班后，下午下班前，结束时间在第二天随意时间点
                    else if (dateAfterLessThan(startDate, afternoonStart) && dateBeforeLessThan(startDate, afternoonEnd)
                            && dateBeforeLessThan(endDate,morningStart1)) {
                        //开始在下午上班后，下午下班前，结束在上午上班前
                        BigDecimal bigDecimal = dateSubtractionDate(startDate, afternoonEnd, DateTimeEnum.Hour);
                        total = total.add(bigDecimal).add(hours);
                    }
                    else if (dateAfterLessThan(startDate, afternoonStart) && dateBeforeLessThan(startDate, afternoonEnd)
                            && dateBeforeLessThan(endDate,morningEnd1) && dateAfterLessThan(endDate,morningStart1)) {
                        //开始在下午上班后，下午下班前，结束在下午上班后，上午下班前
                        BigDecimal bigDecimal = dateSubtractionDate(startDate, afternoonEnd, DateTimeEnum.Hour);
                        BigDecimal decimal = dateSubtractionDate(morningStart1, endDate, DateTimeEnum.Hour);
                        total = total.add(bigDecimal).add(decimal).add(hours);
                    }else if (dateAfterLessThan(startDate, afternoonStart) && dateBeforeLessThan(startDate, afternoonEnd)
                            && dateBeforeLessThan(endDate,afternoonStart1) && dateAfterLessThan(endDate,morningEnd1)) {
                        //开始在下午上班后，下午下班前，结束在下午上班前，上午下班后（中午休息时间）
                        BigDecimal bigDecimal = dateSubtractionDate(startDate, afternoonEnd, DateTimeEnum.Hour);
                        total = total.add(bigDecimal).add(morningHour).add(hours);
                    }else if (dateAfterLessThan(startDate, afternoonStart) && dateBeforeLessThan(startDate, afternoonEnd)
                            && dateAfterLessThan(endDate, afternoonStart1) && dateBeforeLessThan(endDate, afternoonEnd1)) {
                        //开始在下午上班后，下午下班前，结束在下午上班后，下班下班前
                        BigDecimal bigDecimal = dateSubtractionDate(startDate, afternoonEnd, DateTimeEnum.Hour);
                        BigDecimal decimal = dateSubtractionDate(afternoonStart1, endDate, DateTimeEnum.Hour);
                        total = total.add(bigDecimal).add(morningHour).add(decimal).add(hours);
                    } else if (dateAfterLessThan(startDate, afternoonStart) && dateBeforeLessThan(startDate, afternoonEnd)
                            && (dateAfterLessThan(endDate, afternoonEnd1) || endDate.getTime() == afternoonEnd1.getTime())) {
                        //开始在下午上班后，下午下班前，结束在下午下班后
                        BigDecimal bigDecimal = dateSubtractionDate(startDate, afternoonEnd, DateTimeEnum.Hour);
                        total = total.add(bigDecimal).add(morningHour).add(afternoonHour).add(hours);
                    }
                    //开始时间在下午下班后，结束时间在第二天随意时间点
                    else if ((dateAfterLessThan(startDate,afternoonEnd) || startDate.getTime() == afternoonEnd.getTime())
                            && dateBeforeLessThan(endDate,morningStart1)) {
                        //开始时间在下午下班后，结束时间在上午上班前
                        total = total.add(hours);
                    }else if ((dateAfterLessThan(startDate,afternoonEnd) || startDate.getTime() == afternoonEnd.getTime())
                            && dateBeforeLessThan(endDate,morningEnd1) && dateAfterLessThan(endDate,morningStart1)) {
                        //开始时间在下午下班后，结束时间在上午上班后，上午下班前
                        BigDecimal bigDecimal = dateSubtractionDate(morningStart1, endDate, DateTimeEnum.Hour);
                        total = total.add(bigDecimal).add(hours);
                    }else if ((dateAfterLessThan(startDate,afternoonEnd) || startDate.getTime() == afternoonEnd.getTime())
                            && dateBeforeLessThan(endDate,afternoonStart1) && dateAfterLessThan(endDate,morningEnd1)) {
                        //开始时间在下午下班后，结束时间在上午下班后，下午上班前（中午休息时间）
                        total = total.add(morningHour).add(hours);
                    }else if ((dateAfterLessThan(startDate,afternoonEnd) || startDate.getTime() == afternoonEnd.getTime())
                            && dateAfterLessThan(endDate, afternoonStart1) && dateBeforeLessThan(endDate, afternoonEnd1)) {
                        //开始时间在下午下班后，结束时间在下午上班后，下午下班前
                        BigDecimal bigDecimal = dateSubtractionDate(afternoonStart1, endDate, DateTimeEnum.Hour);
                        total = total.add(morningHour).add(bigDecimal).add(hours);
                    }else if ((dateAfterLessThan(startDate,afternoonEnd) || startDate.getTime() == afternoonEnd.getTime())
                            && (dateAfterLessThan(endDate, afternoonEnd1) || endDate.getTime() == afternoonEnd1.getTime())) {
                        //开始时间在下午下班后，结束时间在下午下班后
                        total = total.add(morningHour).add(afternoonHour).add(hours);
                    }else {
                        log.info("DateTimeUtil_getNaturalDayRandomDatePoint_error_same3Day {},{}",JSONObject.toJSONString(startDate),JSONObject.toJSONString(endDate));
                    }
                    total = total.setScale(2,BigDecimal.ROUND_HALF_UP);
                    return total;
                }
                log.info("DateTimeUtil_getNaturalDayRandomDatePoint_error_same4Day {},{},{}",size,JSONObject.toJSONString(startDate),JSONObject.toJSONString(endDate));
                return BigDecimal.ZERO;
            }
        }
    }

    public static Date getMaxEndDateByDate(Date date){
        if(Objects.isNull(date)){
            date = new Date();
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE,59);
        calendar.set(Calendar.SECOND,59);
        calendar.set(Calendar.MILLISECOND,0);
        return calendar.getTime();
    }

}
